﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Threading.Tasks;

namespace BassTutor.Analysis
{
    class SoundAnaliser
    {
        private SoundCapture Source;
        private readonly int BytesPerSample;
        private readonly int SampleRate;
        
        private IDFT fft;
        private double[] olddata;
        
        public SoundAnaliser(SoundCapture Source)
        {
            olddata=null;
            fft = new FFT();
            this.Source = Source;
            this.Source.DataAvailable += Analize;
            BytesPerSample = Source.WaveFormat.BitsPerSample / 8;
            SampleRate = Source.WaveFormat.SampleRate;
            if (Source.WaveFormat.Encoding.ToString() != "Pcm")
                throw new Exception("data format distinct from pcm");
        }

        public event Action<Model.Note> NoteRecognized;

        /// <summary>
        /// Fulfil data length to be power of two, adding old data, if old data is not enought then add mirror
        /// </summary>
        /// <param name="data">data to be adjusted</param>
        /// <returns>adjused data</returns>
        private double[] Extend(double[] data)
        {
            int i,k,len = data.Length;
            for (i = 1; i < len; i <<=1 ) ; //i*=2 - adjust to be power of two
            int gap = i - len;
            double[] res = new double[i];

            for (i = 0; i < len; ++i)
                res[i + gap] = data[i];

            for(i= gap, k = olddata.Length-1; i>=0 && k>=0; --i, --k)
                res[i]=olddata[k];

            for (k = i; i > 0; --i, ++k)
                res[i] = res[k];

            return res;
        }

        private void Analize(int raw_len, byte[] raw_data)
        {
            if (olddata == null)
                olddata = ComputeData(raw_len, raw_data);
            else
            {
                double[] data, fq_data;
                data = ComputeData(raw_len, raw_data);

                //fft would give resolution about 5hz with is to much for lower ferquencioes
                fq_data = fft.dft(Extend(data));
                //Analize data
                //print note
            }
        }

        private double[] ComputeData(int raw_len, byte[] raw_data)
        {
            int len = raw_len / BytesPerSample;     //adjust to real amount of data
 
            double[] data = new double[len];
            int _byte;
            int value;
            double denom = 1 << (8*BytesPerSample);
            
            for (int i = 0; i < len; ++i)
            {
                value = 0;
                for (int j = 0, k = BytesPerSample * i; j < BytesPerSample; ++j)
                {
                    _byte = raw_data[k+j];
                    value = (value << 8) | _byte;
                }
                data[i] = value / denom;
            }
            return data;
        }
    }
}
